[opt](merge into) Put MERGE INTO target on the probe side - #66565
[opt](merge into) Put MERGE INTO target on the probe side#66565starocean999 wants to merge 1 commit into
Conversation
|
Thank you for your contribution to Apache Doris. Please clearly describe your PR:
|
|
run buildall |
TPC-H: Total hot run time: 28909 ms |
TPC-DS: Total hot run time: 167601 ms |
ClickBench: Total hot run time: 23.83 s |
FE UT Coverage ReportIncrement line coverage |
FE Regression Coverage ReportIncrement line coverage |
morrySnow
left a comment
There was a problem hiding this comment.
Thanks for the PR! The semantic equivalence between source LEFT_OUTER target and target RIGHT_OUTER source is correct, and moving the target to the probe side so runtime filters can benefit is a solid optimization. The extraction into MergeUtils is clean.
I submitted a few minor inline comments for consideration — none are blocking. LGTM overall.
| * Build the base join between merge target and source, with the target on the LEFT (probe) | ||
| * side. Doris builds the hash table on the right child, and the target side is structurally | ||
| * the wide one: it must carry every table column plus the row identity for the sink, while | ||
| * the source usually only carries join keys and new values. Keeping the target on the probe |
There was a problem hiding this comment.
The Javadoc mentions that "Doris builds the hash table on the right child" — it would be helpful to also explicitly note that (which excludes but allows and ) is a co-motivator for this choice. This makes the rationale self-contained for future readers who might wonder why RIGHT_OUTER was chosen over LEFT_OUTER.
| LogicalPlan result = (LogicalPlan) generateBasePlan.invoke(command); | ||
| Assertions.assertInstanceOf(LogicalJoin.class, result); | ||
| LogicalJoin<?, ?> logicalJoin = (LogicalJoin<?, ?>) result; | ||
| // WHEN NOT MATCHED needs the unmatched source rows: source is the preserved right side |
There was a problem hiding this comment.
The new test asserts the left child is a LogicalSubQueryAlias but does not verify the alias value. For consistency with testGenerateBasePlanWithAlias (which extracts the alias and asserts .getAlias() equals "alias"), consider adding the same assertion here.
| * Build the base join between merge target and source, with the target on the LEFT (probe) | ||
| * side. Doris builds the hash table on the right child, and the target side is structurally | ||
| * the wide one: it must carry every table column plus the row identity for the sink, while | ||
| * the source usually only carries join keys and new values. Keeping the target on the probe |
There was a problem hiding this comment.
The Javadoc mentions that "Doris builds the hash table on the right child" — it would be helpful to also explicitly note that RuntimeFilterGenerator.DENIED_JOIN_TYPES (which excludes LEFT_OUTER_JOIN but allows RIGHT_OUTER_JOIN and INNER_JOIN) is a co-motivator for this choice. This makes the rationale self-contained for future readers who might wonder why RIGHT_OUTER was chosen over LEFT_OUTER.
|
Minor observation: The |
|
PR approved by at least one committer and no changes requested. |
|
PR approved by anyone and no changes requested. |
Issue Number: close #66435
Related PR: #xxx
Problem Summary:
Doris builds the hash table on the right child, so the structurally wide side — the target must carry all columns plus the row identity (for Iceberg: struct<file_path, row_position, ...> with a full S3 URI per row) — always became the build side. Worse, LEFT_OUTER_JOIN is in DENIED_JOIN_TYPES, so the merge join could never produce runtime filters at all. The internal OLAP path (MergeIntoCommand) used LEFT_OUTER_JOIN unconditionally, even without WHEN NOT MATCHED clauses (the external path already had the INNER optimization). For reference, Trino plans MERGE as target RIGHT JOIN source and only allows dynamic filters on INNER || RIGHT — exactly complementary to Doris's denied list.
Release note
None
Check List (For Author)
Test
Behavior changed:
Does this need documentation?
Check List (For Reviewer who merge this PR)